﻿using SqlSugar;
using System.Data;

namespace MassTransitTest.SqlSugarCore
{
    public class ContextBase : IDbHelper
    {
        private SqlSugarClient sqlSugarClient;

        public SqlSugarClient Client { get { return sqlSugarClient; } }

        public ContextBase(string connectString, DbTypeEnum dbType)
            : this(connectString, dbType, null)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connectString"></param>
        /// <param name="dbType"></param>
        /// <param name="slaveConfigs">从库列表，null表示不启用从库</param>
        public ContextBase(string connectString, DbTypeEnum dbType, List<SlaveConfig>? slaveConfigs)
        {
            sqlSugarClient = new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = connectString,
                DbType = ConvertDbType(dbType),
                IsAutoCloseConnection = true,
                SlaveConnectionConfigs = slaveConfigs == null ? null : slaveConfigs.Select(p => new SlaveConnectionConfig { HitRate = p.HitRate, ConnectionString = p.ConnectString }).ToList()
            });
            //每次Sql执行前事件
            sqlSugarClient.Aop.OnLogExecuting = (sql, pars) =>
            {
                Console.WriteLine(sql);//输出sql,查看执行sql
            };
            //SQL执行完
            sqlSugarClient.Aop.OnLogExecuted = (sql, pars) =>
            {
                Console.WriteLine(sql);//输出sql,查看执行sql
            };
            //SQL报错
            sqlSugarClient.Aop.OnError = (ex) =>
            {
                Console.WriteLine(ex.Sql);//输出sql,查看执行sql
            };
            //可以修改SQL和参数的值
            sqlSugarClient.Aop.OnExecutingChangeSql = (sql, pars) =>
            {
                //sql=newsql
                //foreach(var p in pars) //修改
                return new KeyValuePair<string, SugarParameter[]>(sql, pars);
            };
        }

        public void BeginTrans(IsolationLevel? isolationLevel)
        {
            if (sqlSugarClient is null)
            {
                throw new InvalidOperationException("sqlSugarClient未初始化");
            }
            if (isolationLevel == null)
            {
                sqlSugarClient.Ado.BeginTran();
            }
            else
            {
                sqlSugarClient.Ado.BeginTran(isolationLevel.Value);
            }

        }

        public int BulkInsert(DataTable table, bool close = true, int? timeout = null)
        {
            try
            {
                sqlSugarClient.Ado.CommandTimeOut = GetTimeOut(timeout);
                return sqlSugarClient.Fastest<DataTable>().AS(table.TableName).BulkCopy(table.TableName, table);
            }
            catch (Exception e)
            {
                throw;
            }
            finally
            {
                if (close)
                    CloseConnection();
            }

        }

        public void Commit(bool close = true)
        {
            if (sqlSugarClient is null)
            {
                throw new InvalidOperationException("sqlSugarClient未初始化");
            }
            sqlSugarClient.Ado.CommitTran();
        }

        public void Dispose()
        {
            if (sqlSugarClient is not null)
            {
                sqlSugarClient.Dispose();
            }
        }

        public int Excute(string sql, object? param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null)
        {
            try
            {
                sqlSugarClient.Ado.CommandType = commandType;
                sqlSugarClient.Ado.CommandTimeOut = GetTimeOut(timeout);
                return sqlSugarClient.Ado.ExecuteCommand(sql, param);
            }
            catch (Exception e)
            {
                throw;
            }
            finally
            {
                if (close)
                {
                    CloseConnection();
                }
            }

        }

        public int Excute(string sql, IEnumerable<object> paramList, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null)
        {
            throw new NotImplementedException();
        }

        public TV ExecuteScalar<TV>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null)
        {
            throw new NotImplementedException();
        }

        public bool IsTransOpen()
        {
            throw new NotImplementedException();
        }

        public DataTable Query(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null)
        {
            try
            {
                sqlSugarClient.Ado.CommandType = commandType;
                sqlSugarClient.Ado.CommandTimeOut = GetTimeOut(timeout);
                return sqlSugarClient.Ado.GetDataTable(sql, param);
            }
            catch (Exception e)
            {
                throw;
            }
            finally
            {
                if (close)
                {
                    CloseConnection();
                }
            }
        }

        public T QueryFirstOrDefault<T>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null) where T : class
        {
            throw new NotImplementedException();
        }

        public IEnumerable<T> QueryMultiple<T>(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null) where T : class
        {
            try
            {
                sqlSugarClient.Ado.CommandType = commandType;
                sqlSugarClient.Ado.CommandTimeOut = GetTimeOut(timeout);
                return sqlSugarClient.Ado.SqlQuery<T>(sql, param);
            }
            catch (Exception e)
            {
                throw;
            }
            finally
            {
                if (close)
                {
                    CloseConnection();
                }
            }
        }

        public DataTable QueryWithKeyInfo(string sql, object param = null, CommandType commandType = CommandType.Text, bool close = true, int? timeout = null)
        {
            try
            {
                var table = new DataTable();
                sqlSugarClient.Ado.CommandType = commandType;
                sqlSugarClient.Ado.CommandTimeOut = GetTimeOut(timeout);
                using (var reader = sqlSugarClient.Ado.GetDataReader(sql, param))
                {

                    table.Load(reader);
                }
                return table;
            }
            catch (Exception e)
            {
                throw;
            }
            finally
            {
                if (close)
                    CloseConnection();
            }
        }

        public void Rollback(bool close = true)
        {
            if (sqlSugarClient is null)
            {
                throw new InvalidOperationException("sqlSugarClient未初始化");
            }
            sqlSugarClient.Ado.RollbackTran();
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        protected void CloseConnection()
        {
            if (sqlSugarClient is not null)
            {
                sqlSugarClient.Close();
            }
        }

        /// <summary>
        /// 获取超时时间
        /// </summary>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        protected int GetTimeOut(int? timeOut)
        {
            if (timeOut == null)
            {
                return DbConst.DefaultTimeOut;
            }
            return timeOut.Value;
        }

        protected SqlSugar.DbType ConvertDbType(DbTypeEnum dbType)
        {
            switch (dbType)
            {
                case DbTypeEnum.SqlServer:
                    return SqlSugar.DbType.SqlServer;
                case DbTypeEnum.Mysql:
                    return SqlSugar.DbType.MySql;
                case DbTypeEnum.SqlLite:
                    return SqlSugar.DbType.Sqlite;
                case DbTypeEnum.PostGreSql:
                    return SqlSugar.DbType.PostgreSQL;
            }
            throw new NotImplementedException($"数据库{dbType.ToString()}暂不支持");
        }
    }
}
